# -*- coding: utf-8 -*-

# -------------------------------
# Author    : linlingwei
# Email     : 951035650@qq.com
# File Name : animCurveCmds.py
# Date      : 2019/10/10
# IDE       : PyCharm
# Version   : 1.0.1
# -------------------------------
import os
import sys
import json

import maya.cmds as mc
import maya.mel as mel
# import configs.constants.global_constant as gc

import scripts.commonCmds as con

sdkNodeType = ["animCurveUL","animCurveUA","animCurveUT","animCurveUU"]

def _renameAnimCurveNode(inputNode):
    inobj,inattr = findObj_driver(inputNode)
    outobj,outattr = findObj_driver(inputNode)
    
    nn = "%s_%s_to_%s_%s"%(inobj,inattr,outobj,outattr)
    mc.rename(inputNode,nn)
    return nn

def ifSdkNode(inNode,sdklist,mode=1):
    nt = mc.nodeType(inNode)
    # print nt
    if nt in sdkNodeType:
        sdklist.append(inNode)
    elif nt == "unitConversion":
        if mode == 1:
            ulc = mc.listConnections(inNode, s=False, d=True)
        elif mode == 2:
            ulc = mc.listConnections(inNode, s=True, d=False)
        if ulc:
            ifSdkNode(ulc[0],sdklist,mode)
    elif nt == "blendWeighted":
        bwCon = mc.listConnections(inNode, s=True, d=False)
        if bwCon:
            for bc in bwCon:
                ifSdkNode(bc,sdklist,mode)
    else:
        return
    
def findSdkNode_output(obj):
    listCon = mc.listConnections(obj,s=False,d=True)
    if not listCon:
        return
    sdkNodeList = list()
    for lc in listCon:
        ifSdkNode(lc,sdkNodeList)
    return sdkNodeList

def findSdkNode_input(obj):
    listCon = mc.listConnections(obj,s=True,d=False)
    if not listCon:
        return
    sdkNodeList = list()
    for lc in listCon:
        ifSdkNode(lc,sdkNodeList,2)
    return sdkNodeList

def findObj_driver(sdkNode):
    _return = list()
    _nextConnect(sdkNode, True, False,_return)
    return _return[0]
def findObj_driverList(obj):
    obj_list = list()
    connect = findSdkNode_output(obj)
    if connect:
        for c in connect:
            obj=findObj_driven(c)[0]
            if obj not in obj_list:
                obj_list.append(obj)
    return obj_list

def findObj_DrivenList(obj):
    obj_list = list()
    connect = findSdkNode_input(obj)
    if connect:
        for c in connect:
            obj=findObj_driver(c)[0]
            if obj not in obj_list:
                obj_list.append(obj)
    return obj_list


def findObj_driven(sdkNode):
    _return = list()
    _nextConnect(sdkNode, False, True,_return)
    return _return[0]
def _nextConnect(node,s=True,d=False,_return=None):
    # print node
    nc = mc.listConnections(node, s=s, d=d)
    if nc:
        for n in nc:
            # print n
            nt = mc.nodeType(n)
            if nt in ["unitConversion","blendWeighted"]:
                _nextConnect(n, s=s, d=d,_return=_return)
            else:
                # print node,n
                _driver_attr = mc.listConnections(node, s=s, d=d, p=True)
                # print _driver_attr
                if _driver_attr:
                    _return.append( _driver_attr[0].split("."))

def find_driverAttr(obj):
    sdklist = findSdkNode_output(obj)
    attrlist = []
    for sl in sdklist:
        attr = findObj_driver(sl)[1]
        if attr not in attrlist:
            attrlist.append(attr)
    return attrlist

def find_attrToDriven(obj,attr):
    objlist = list()
    sdks = findSdkNode_output(con.lAttr(obj,attr))
    if sdks:
        for sdk in sdks :
            obj = findObj_driven(sdk)
            if obj[0] not in objlist:
                objlist.append(obj[0])
    # print objlist
    return objlist

def getTimeValue(sdkNode):
    tv_list= []
    attrList = mc.listAttr("%s.ktv"%sdkNode, m=1)
    for al in attrList:
        if "." not in al:
            t = mc.getAttr("%s.%s.keyTime"%(sdkNode,al))
            v = mc.getAttr("%s.%s.keyValue" % (sdkNode, al))
            tv_list.append([t,v])

    return tv_list

def getSdkData(sdkNode):

    times = mc.keyframe(sdkNode, q=1, fc=1)
    if times:
        values = mc.keyframe(sdkNode, q=1, vc=1)
    
        itts = mc.keyTangent(sdkNode, q=1, itt=1)
        otts = mc.keyTangent(sdkNode, q=1, ott=1)
    
        ias = mc.keyTangent(sdkNode, q=1, ia=1)
        oas = mc.keyTangent(sdkNode, q=1, oa=1)
        weighted = mc.keyTangent(sdkNode, q=1, wt=1)
        pre = mc.getAttr(sdkNode + '.preInfinity')
        post = mc.getAttr(sdkNode + '.postInfinity')
    
        drObj, drAttr = findObj_driver(sdkNode)
        dnObj, dnAttr = findObj_driven(sdkNode)
        
        
        data = {"drObj": drObj,
                "drAttr": drAttr,
                "dnObj": dnObj,
                "dnAttr": dnAttr,
                "pre": pre,
                "post": post}
        
        tvlist=list()
        for i in range(len(times)):
            tv = {"time":times[i],
                  "value":values[i],
                  "itt":itts[i],
                  "ott":otts[i],
                  "ia":ias[i],
                  "oa":oas[i]}
            tvlist.append(tv)
        data["time_value"] = tvlist
        return data

def list_sdkNode():
    
    sdkList = list()
    for nt in sdkNodeType:
        ac = mc.ls(typ=nt,fl=True)
        sdkList.extend(ac)
    return sdkList

def setSdk(sdkData,drobj,drattr,dnobj,dnattr):
    
    dr = con.lAttr(drobj,drattr)
    dn = con.lAttr(dnobj,dnattr)
    
    for i,tv in enumerate(sdkData["time_value"]):
        time = tv["time"]
        value = tv["value"]

        sdks = findSdkNode_output(con.lAttr(dnobj, dnattr))
        print sdks
        mc.delete(sdks)
        mc.setDrivenKeyframe(dn, cd=dr, dv=time, v=value,itt="auto",ott="auto")
        
    for i, tv in enumerate(sdkData["time_value"]):
        sdkNode = findSdkNode_input(dn)[0]
        # print sdkNode
        itt = tv["itt"]
        ott = tv["ott"]
        ia = tv["ia"]
        oa = tv["oa"]
        mel.eval('keyTangent -index %s -e -itt %s -ott %s %s' % (i, itt, ott, sdkNode))
        mel.eval('keyTangent -index %s -e -ia %s -oa %s %s' % (i, float(ia), float(oa), sdkNode))

    return

def exportData(fpath,sdkNode):
    
    if os.path.exists(fpath):
        with open(fpath,"r") as rf:
            sdata = json.load(rf)
    else:
        sdata = {}
        
    drObj, drAttr = findObj_driver(sdkNode)
    dnObj, dnAttr = findObj_driven(sdkNode)
    keyName = "%s.%s&%s.%s"%(drObj, drAttr,dnObj, dnAttr)

    data = {keyName:getSdkData(sdkNode)}
    
    output_dict = dict(sdata,**data)
    with open(fpath,"w") as f:
        json.dump(output_dict,f,sort_keys=True,indent=4, separators=(',', ': '))
    return

def importData(fpath,obj):

    return

def mirror_objSdk_to(sobj, lf_tag="L_", rt_tag="R_"):
    if lf_tag not in sobj:
        return
    tobj = sobj.replace(lf_tag, rt_tag)
    if not mc.objExists(tobj):
        return
    
    sdks = findSdkNode_output(sobj)
    for sn in sdks:
        drObj, drAttr = findObj_driver(sn)
        dnObj, dnAttr = findObj_driven(sn)

        # t_sdrObj = drObj.replace(ltag,rtag)
        t_sdnObj = dnObj.replace(lf_tag, rt_tag)
        
        if not mc.objExists(t_sdnObj):
            continue
        data = getSdkData(sn)
        setSdk(data,tobj,drAttr,t_sdnObj,dnAttr)

    return

if __name__ == '__main__':
    pass